import sys
import re
import time

from PyQt5.QtWidgets import *
from untitled import Ui_MainWindow
from PyQt5.QtCore import Qt, QThread
import ProceDataLayer as PDL
import os
from commonData import ComData as cd
import pandas


class MyMainForm(QMainWindow, Ui_MainWindow):

    def __init__(self, parent=None):
        super(MyMainForm, self).__init__(parent)
        self.setupUi(self)
        self.month_pre = 1  # 第一个月
        self.month_next = 1  # 第二个月
        self.day1 = 1
        self.day2 = 1
        self.data_type = "平均值"
        self.selectInfo = []  # 当前选中的数据，用于添加到处理指标中去
        self.staion_excel = None
        self.file_out2 = None  # 提取出来的文件夹的
        self.file_pre_or_tem = None  # 降水or气温的文件夹所载的位置
        self.all_one_type = [self.one_max, self.one_min, self.one_average, self.one_sum, self.one_mode,
                             self.one_stand_dev, self.one_median, self.one_change_range]
        self.all_two_type = [self.two_max, self.two_min, self.two_average, self.two_variance, self.two_change_range]

        self.setWindowTitle(cd.title + cd.version)
        for i in range(1, 32):
            self.combox_day1.addItem(str(i) + '日')  # 首先给日赋值
            self.combox_day2.addItem(str(i) + '日')

        """信号槽"""
        self.button_choice.clicked.connect(self.getChoiceFile)
        self.button_choice_put.clicked.connect(self.getOutfile)

        self.combox_month_pre.currentIndexChanged.connect(self.changeMonthPre)  # 第一个月的更改
        self.combox_month_next.currentIndexChanged.connect(self.changeMonthNext)  # 第二个月的更改
        self.combox_day1.currentIndexChanged.connect(self.changeDay1)
        self.combox_day2.currentIndexChanged.connect(self.changeDay2)
        # self.combox_target.currentIndexChanged.connect(self.changeTarget)

        self.button_delete.clicked.connect(self.Delete)

        self.button_star.clicked.connect(self.Star)
        self.button_end.clicked.connect(self.End)

        self.tree_select.itemChanged.connect(self.onclick1)
        self.line_put_file.textChanged.connect(self.change_put_file)
        self.line_file.editingFinished.connect(self.get_choice_folder_by_edit_finished)

        """第一次处理的槽函数"""
        self.one_max.stateChanged.connect(self.one_type_of_max)
        self.one_min.stateChanged.connect(self.one_type_of_min)
        self.one_sum.stateChanged.connect(self.one_type_of_sum)
        self.one_mode.stateChanged.connect(self.one_type_of_mode)
        self.one_median.stateChanged.connect(self.one_type_of_median)
        self.one_average.stateChanged.connect(self.one_type_of_averange)
        self.one_stand_dev.stateChanged.connect(self.one_type_of_stand_dev)
        self.one_change_range.stateChanged.connect(self.one_type_of_change_range)

        """第二次处理槽函数"""
        self.two_max.stateChanged.connect(self.two_type_of_max)
        self.two_min.stateChanged.connect(self.two_type_of_min)
        self.two_average.stateChanged.connect(self.two_type_of_average)
        self.two_variance.stateChanged.connect(self.two_type_of_variance)
        self.two_change_range.stateChanged.connect(self.two_type_of_change_range)

    def get_abnormal(fun):
        def abnormal(self, *args, **kwargs):
            try:
                return fun(self, *args, **kwargs)
            except Exception as e:
                print("异常信息:{},异常方法:{}".format(e, fun.__name__))

        return abnormal  # 没有返回值

    def get_choice_folder_by_edit_finished(self):
        self.tree_select.clear()
        self.selectInfo = []
        cd.targetInfo = {}
        cd.one_data = []  # 第一次取整处理的数据
        cd.two_data = []  # 第二次处理的数据
        file = self.line_file.text()
        cd.file_in = file
        if file != "":
            self.line_put_file.setText(cd.file_in[:2] + "\\统计值输出")  # 将数据集的盘符作为输出集的位置
            cd.file_out = cd.file_in[:2] + "\\统计值输出"
        if file != "":
            temp_info = []
            if len(temp_info) == 0:
                wb = pandas.ExcelFile(file + "\\" + os.listdir(file)[0])
                for name in wb.sheet_names:
                    if name not in temp_info:
                        temp_info.append(name)

            for name in temp_info:
                root = QTreeWidgetItem(self.tree_select)
                root.setText(0, name)
                root.setCheckState(0, Qt.Unchecked)

    """二次处理函数的实现"""

    def two_type_of_max(self):
        d = '最大值'
        if self.two_max.checkState() == Qt.Checked:
            if d not in cd.two_data:
                cd.two_data.append(d)
        else:
            if d in cd.two_data:
                cd.two_data.remove(d)

    def two_type_of_min(self):
        d = '最小值'
        if self.two_min.checkState() == Qt.Checked:
            if d not in cd.two_data:
                cd.two_data.append(d)
        else:
            if d in cd.two_data:
                cd.two_data.remove(d)

    def two_type_of_average(self):
        d = '平均值'
        if self.two_average.checkState() == Qt.Checked:
            if d not in cd.two_data:
                cd.two_data.append(d)
        else:
            if d in cd.two_data:
                cd.two_data.remove(d)

    def two_type_of_variance(self):
        d = '方差'
        if self.two_variance.checkState() == Qt.Checked:
            if d not in cd.two_data:
                cd.two_data.append(d)
        else:
            if d in cd.two_data:
                cd.two_data.remove(d)

    def two_type_of_change_range(self):
        try:
            d = '变化范围值'
            if self.two_change_range.checkState() == Qt.Checked:
                if d not in cd.two_data:
                    cd.two_data.append(d)
            else:
                if d in cd.two_data:
                    cd.two_data.remove(d)
        except Exception as e:
            print(e)

    """第一次处理的方法"""

    def one_type_of_max(self):
        d = '最大值'
        day_to_day = "{}月{}日至{}月{}日{}".format(self.month_pre, self.day1, self.month_next, self.day2, d)
        if self.one_max.checkState() == Qt.Checked:
            if d not in cd.one_data:
                cd.one_data.append(d)
        else:
            if d in cd.one_data:
                cd.one_data.remove(d)
            for target in self.selectInfo:
                if day_to_day in cd.targetInfo[target]:
                    cd.targetInfo[target].remove(day_to_day)
        MyMainForm.new_target_tree(self)

    def one_type_of_min(self):
        d = '最小值'
        day_to_day = "{}月{}日至{}月{}日{}".format(self.month_pre, self.day1, self.month_next, self.day2, d)
        if self.one_min.checkState() == Qt.Checked:
            if d not in cd.one_data:
                cd.one_data.append(d)
        else:
            if d in cd.one_data:
                cd.one_data.remove(d)
            for target in self.selectInfo:
                if day_to_day in cd.targetInfo[target]:
                    cd.targetInfo[target].remove(day_to_day)
        MyMainForm.new_target_tree(self)

    def one_type_of_sum(self):
        d = '求和'
        day_to_day = "{}月{}日至{}月{}日{}".format(self.month_pre, self.day1, self.month_next, self.day2, d)
        if self.one_sum.checkState() == Qt.Checked:
            if d not in cd.one_data:
                cd.one_data.append(d)
        else:
            if d in cd.one_data:
                cd.one_data.remove(d)
            for target in self.selectInfo:
                if day_to_day in cd.targetInfo[target]:
                    cd.targetInfo[target].remove(day_to_day)
        MyMainForm.new_target_tree(self)

    def one_type_of_mode(self):
        d = '众数'
        day_to_day = "{}月{}日至{}月{}日{}".format(self.month_pre, self.day1, self.month_next, self.day2, d)
        if self.one_mode.checkState() == Qt.Checked:
            if d not in cd.one_data:
                cd.one_data.append(d)
        else:
            if d in cd.one_data:
                cd.one_data.remove(d)
            for target in self.selectInfo:
                if day_to_day in cd.targetInfo[target]:
                    cd.targetInfo[target].remove(day_to_day)
        MyMainForm.new_target_tree(self)

    def one_type_of_median(self):
        d = '中位数'
        day_to_day = "{}月{}日至{}月{}日{}".format(self.month_pre, self.day1, self.month_next, self.day2, d)
        if self.one_median.checkState() == Qt.Checked:
            if d not in cd.one_data:
                cd.one_data.append(d)
        else:
            if d in cd.one_data:
                cd.one_data.remove(d)
            for target in self.selectInfo:
                if day_to_day in cd.targetInfo[target]:
                    cd.targetInfo[target].remove(day_to_day)
        MyMainForm.new_target_tree(self)

    def one_type_of_averange(self):
        d = '平均值'
        day_to_day = "{}月{}日至{}月{}日{}".format(self.month_pre, self.day1, self.month_next, self.day2, d)
        if self.one_average.checkState() == Qt.Checked:
            if d not in cd.one_data:
                cd.one_data.append(d)
        else:
            if d in cd.one_data:
                cd.one_data.remove(d)
            for target in self.selectInfo:
                if day_to_day in cd.targetInfo[target]:
                    cd.targetInfo[target].remove(day_to_day)
        MyMainForm.new_target_tree(self)

    def one_type_of_stand_dev(self):
        d = '标准差'
        day_to_day = "{}月{}日至{}月{}日{}".format(self.month_pre, self.day1, self.month_next, self.day2, d)
        if self.one_stand_dev.checkState() == Qt.Checked:
            if d not in cd.one_data:
                cd.one_data.append(d)
        else:
            if d in cd.one_data:
                cd.one_data.remove(d)
            for target in self.selectInfo:
                if day_to_day in cd.targetInfo[target]:
                    cd.targetInfo[target].remove(day_to_day)
        MyMainForm.new_target_tree(self)

    def one_type_of_change_range(self):
        try:
            d = '变化幅度'
            day_to_day = "{}月{}日至{}月{}日{}".format(self.month_pre, self.day1, self.month_next, self.day2, d)
            if self.one_change_range.checkState() == Qt.Checked:
                if d not in cd.one_data:
                    cd.one_data.append(d)
            else:
                if d in cd.one_data:
                    cd.one_data.remove(d)
                for target in self.selectInfo:
                    if day_to_day in cd.targetInfo[target]:
                        cd.targetInfo[target].remove(day_to_day)
            MyMainForm.new_target_tree(self)
        except Exception as e:
            print(e)

    def set_one_and_two_enable(self, status):
        for t in self.all_one_type:
            t.setEnabled(status)

    def if_enable_one_and_two(self):  # 是否要开启enable
        if len(self.selectInfo) != 0:
            MyMainForm.set_one_and_two_enable(self, True)
        else:
            MyMainForm.set_one_and_two_enable(self, False)

    def new_target_tree(self):  # 第一处理的类型
        for target in self.selectInfo:  # 以选择的
            if target not in cd.targetInfo.keys():  # 如果该指标不在指标信息内, 则是第一次添加，那么不用考虑是否存在日期和统计值的情况
                cd.targetInfo[target] = []  # 添加进指标信息内
                for one in cd.one_data:
                    day_to_day = "{}月{}日至{}月{}日{}".format(self.month_pre, self.day1, self.month_next, self.day2, one)
                    if day_to_day not in cd.targetInfo[target]:
                        cd.targetInfo[target].append(day_to_day)
            else:
                for one in cd.one_data:
                    day_to_day = "{}月{}日至{}月{}日{}".format(self.month_pre, self.day1, self.month_next, self.day2, one)
                    if day_to_day not in cd.targetInfo[target]:
                        cd.targetInfo[target].append(day_to_day)
        self.tree_target.clear()
        for key, values in cd.targetInfo.items():
            root = QTreeWidgetItem(self.tree_target)
            root.setText(0, key)
            for v in values:
                child = QTreeWidgetItem()
                child.setText(0, v)
                root.addChild(child)
        self.tree_target.expandAll()
        # print("更改后:", cd.targetInfo)

    def change_put_file(self):
        cd.file_out = self.line_put_file.text()

    def getOutFile2(self):  # 第二个输出的文件夹的位置
        fileName = QFileDialog.getExistingDirectory(self, directory="C:").replace("/", "\\")  # 获取气温or降水所在的文件夹的位置
        if fileName != '':
            self.line_put_file2.setText(fileName)
            self.file_out2 = fileName

    def getStationFile(self):  # 获取station的txt的文件夹所在的位置
        # fileName, fileType = QFileDialog.getOpenFileName(self, "选取文件", os.getcwd(), "Text Files(*.txt)")  # 选取txt文件
        fileName = QFileDialog.getExistingDirectory(self, directory="C:").replace("/", "\\")  # 获取气温or降水所在的文件夹的位置
        if fileName != '':
            self.line_file_staion.setText(fileName)
            self.file_pre_or_tem = fileName
            self.file_out2 = fileName[:2] + "\\" + "提取出的站点信息"  # 默认放在G盘
            self.line_put_file2.setText(self.file_out2)

    #
    def getChoiceFile(self):  # 获取选中的文件夹
        self.selectInfo = []
        cd.targetInfo = {}
        cd.one_data = []  # 第一次取整处理的数据
        cd.two_data = []  # 第二次处理的数据
        self.temp_info = []
        self.tree_select.clear()
        file = QFileDialog.getExistingDirectory(self, directory="C:").replace("/", "\\")  # 获取文件
        self.line_file.setText(file)
        cd.file_in = file
        if file != "":
            self.line_put_file.setText(cd.file_in[:2] + "\统计值输出")  # 将数据集的盘符作为输出集的位置
            cd.file_out = cd.file_in[:2] + "\统计值输出"
        if file != "":
            temp_info = []
            if len(temp_info) == 0:
                wb = pandas.ExcelFile(file + "\\" + os.listdir(file)[0])
                for name in wb.sheet_names:
                    if name not in temp_info:
                        temp_info.append(name)
            self.temp_info = temp_info[:]

            for name in temp_info:
                root = QTreeWidgetItem(self.tree_select)
                root.setText(0, name)
                root.setCheckState(0, Qt.Unchecked)

    def onclick1(self, item, state):  # 选中指标的槽函数
        info = item.text(0)
        if item.checkState(state) == Qt.Checked:
            self.selectInfo.append(info)
        else:
            if info in self.selectInfo:  # 如果未选中并且数据在内
                self.selectInfo.remove(info)
                if info in cd.targetInfo.keys():
                    del cd.targetInfo[info]
        # print(cd.targetInfo)
        MyMainForm.if_enable_one_and_two(self)
        MyMainForm.new_target_tree(self)

    def getOutfile(self):
        file = QFileDialog.getExistingDirectory(self, directory="C:").replace("/", "\\")  # 获取文件
        self.line_put_file.setText(file)
        cd.file_out = file
        if file == '':
            self.line_put_file.setText(cd.file_in[:2] + "\统计值输出")  # 将数据集的盘符作为输出集的位置
            cd.file_out = cd.file_in[:2] + "\统计值输出"

    def changeDay1(self):
        if self.combox_day1.currentText() != "":
            self.day1 = int(re.findall(r'(\d+)', self.combox_day1.currentText())[0])
        self.tree_target.clear()
        cd.targetInfo = {}
        MyMainForm.new_target_tree(self)

    def changeDay2(self):
        if self.combox_day2.currentText() != "":
            self.day2 = int(re.findall(r'(\d+)', self.combox_day2.currentText())[0])
            if self.day2 < self.day1 and self.month_next == self.month_pre:  # 相同月份的时候，第二个日子应该大于第一个日子
                msg_box = QMessageBox(QMessageBox.Warning, '输入错误', '第二个日子应该大于第一个日子')
                msg_box.exec_()
                self.combox_day2.setCurrentText(str(self.day1 + 1) + '日')
                self.day2 = self.day1 + 1
        self.tree_target.clear()
        cd.targetInfo = {}
        MyMainForm.new_target_tree(self)

    def changeMonthPre(self):
        # 2月设定为29天，选定29天表示如果处理的是闰年，那么要考虑29天，否则是28天
        month_day = [0, 31, 29, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31]
        month = self.combox_month_pre.currentText()
        # self.month_pre = self.combox_month_pre.itemText(index)
        month = int(re.findall(r'(\d+)', month)[0])
        self.month_pre = month
        if self.combox_day1.count() != month_day[month]:  # 如果最大天数小于这个，说明需要重新计算
            self.combox_day2.clear()
            self.combox_day1.clear()
            for i in range(1, month_day[month] + 1):
                self.combox_day1.addItem(str(i) + '日')
                self.combox_day2.addItem(str(i) + '日')
        self.tree_target.clear()
        cd.targetInfo = {}
        MyMainForm.new_target_tree(self)

    def changeMonthNext(self):
        month = self.combox_month_next.currentText()
        month = int(re.findall(r'(\d+)', month)[0])  # 下一个月的
        self.month_next = month
        if self.month_pre > self.month_next:
            msg_box = QMessageBox(QMessageBox.Warning, '输入错误', '前一个月份应该小于或等于后一个月份')
            msg_box.exec_()
        self.tree_target.clear()
        cd.targetInfo = {}
        MyMainForm.new_target_tree(self)

    def changeType(self):
        self.data_type = self.combox_data_type.currentText()

    def Star(self):
        if self.day2 < self.day1 and self.month_next == self.month_pre:
            msg_box = QMessageBox(QMessageBox.Warning, '输入错误', '第一个日期应该小于第二个日期')
            msg_box.exec_()
            self.combox_day1.setCurrentText(str(self.day2 - 1) + '日')
        else:
            self.thread = MyThread()
            self.thread.start()  # start调用的是run

    def End(self):
        sys.exit(app.exec_())

    def Delete(self):
        try:
            item = self.tree_target.currentItem()
            root = self.tree_target.invisibleRootItem()
            if item.parent() != None:
                target = item.parent().text(0)  # 获取父节点的信息,就是twice_info 的一级key
                cd.targetInfo[target].remove(str(item.text(0)))  # 删除选中的子节点
            else:
                del cd.targetInfo[item.text(0)]  # 如果是删除父节点
                self.selectInfo.remove(item.text(0))  # 在选中里面进行删除
                self.tree_select.clear()
                for name in self.temp_info:
                    if name in self.selectInfo:
                        root = QTreeWidgetItem(self.tree_select)
                        root.setText(0, name)
                        root.setCheckState(0, Qt.Checked)
                    else:
                        root = QTreeWidgetItem(self.tree_select)
                        root.setText(0, name)
                        root.setCheckState(0, Qt.Unchecked)

            for item in self.tree_target.selectedItems():
                (item.parent() or root).removeChild(item)
            # print("删除后:", cd.targetInfo)
        except Exception as e:
            msg_box = QMessageBox(QMessageBox.Warning, '删除错误', '未选中要删除的数据')
            msg_box.exec_()


class MyThread(QThread):

    def __init__(self):
        super(MyThread, self).__init__()

    def run(self):
        startTime = time.time()
        try:
            PDL.Data().start()
        except Exception as e:
            print("输入信息有误或是无有效输入!")
        print("处理完毕, 用时%.2f秒,%.2f分钟" % (time.time() - startTime, (time.time() - startTime) / 60))


if __name__ == '__main__':
    app = QApplication(sys.argv)
    myWin = MyMainForm()
    myWin.show()
    sys.exit(app.exec_())
